package org.kernely.security.shiro;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.kernely.security.dao.UserDAO;
import org.kernely.security.persistence.Permission;
import org.kernely.security.persistence.Role;
import org.kernely.security.persistence.User;

/**
 * Definition of a Realm specific to Kernely Application
 */
public class KernelyRealm extends AuthorizingRealm{

	@Override
	/**
	 * Redefinition of AuthorizingRealm method.
	 */
	protected final AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
		UserDAO userdao = UserDAO.getInstance();

		String username = upToken.getUsername();
		checkNotNull(username, "Null usernames are not allowed by this realm.");

		String password = userdao.getUserPassword(username);
		checkNotNull(password, "No account found for user [" + username + "]");

		// Check if the user is enabled
		int enabled = userdao.findUser(username).getEnabled();
		if (enabled == 0) {
			throw new LockedAccountException("This account is disabled.");
		}

		return new SimpleAuthenticationInfo(username, password.toCharArray(), getName());
	}

	private final void checkNotNull(Object reference, String message) {
		if (reference == null) {
			throw new AuthenticationException(message);
		}
	}

	@Override
	protected final AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		UserDAO userdao = UserDAO.getInstance();
		String username = (String)principals.fromRealm(getName()).iterator().next();
		User user = userdao.findUser(username);
		if (user != null) {
			SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
			for (Role role : user.getAllRoles()) {
				info.addRole(role.getName());
			}
			for (Permission perm : user.getAllPermissions()) {
				info.addStringPermission(perm.getName());
			}
			return info;
		} else {
			return null;
		}
	}

}
